﻿using System;
using System.Web;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using VioletDevelopmentLaboratory.Net.Data;
using VioletDevelopmentLaboratory.Net.Web.Configuration;

namespace VioletDevelopmentLaboratory.Net.Web.Component
{
	public class BoardCategory
	{
		private String applicationName;
		public String ApplicationName { get { return this.applicationName; } internal set { this.applicationName = value; } }

		private String categoryID;
		public String CategoryID { get { return this.categoryID; } internal set { this.categoryID = value; } }

		private String componentID;
		public String ComponentID { get { return componentID; } internal set { componentID = value; } }

		private String name;
		public String Name { get { return this.name; } internal set { this.name = value; } }

		private Int32 index;
		public Int32 Index { get { return this.index; } internal set { this.index = value; } }

		private Boolean hasIconImage;
		public Boolean HasIconImage { get { return hasIconImage; } internal set { this.hasIconImage = value; } }

		private String iconImageUrl;
		public String IconImageUrl { get { return this.iconImageUrl; } internal set { this.iconImageUrl = value; } }

		private Int64 threadCount;
		public Int64 ThreadCount { get { return this.threadCount; } internal set { this.threadCount = value; } }

		public static BoardCategoryCreateResult Create(String componentID, String name, Int32 index)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_CreateWithoutIcon",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@Name", name),
				new SqlParameter("@Index", index)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryCreateResult.Success;
				default:
					return BoardCategoryCreateResult.Exists;
			}
		}

		public static BoardCategoryCreateResult Create(String componentID, String name, Int32 index, HttpPostedFile iconFile)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			if (iconFile == null)
				throw new ArgumentNullException("iconFile");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_Create",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@Name", name),
				new SqlParameter("@Index", index),
				new SqlParameter("@IconImage", getImageBytes(iconFile)),
				new SqlParameter("@IconContentType", iconFile.ContentType),
				new SqlParameter("@IconLength", iconFile.ContentLength)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryCreateResult.Success;
				default:
					return BoardCategoryCreateResult.Exists;
			}
		}

		public static BoardCategoryUpdateResult Modify(String componentID, String categoryID, String name, Int32 index)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			Object returnValue;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_UpdateWithoutIcon",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID),
				new SqlParameter("@Name", name),
				new SqlParameter("@Index", index)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryUpdateResult.Success;
				default:
					return BoardCategoryUpdateResult.InvalidCategory;
			}
		}

		public static BoardCategoryUpdateResult Modify(String componentID, String categoryID, String name, Int32 index, HttpPostedFile iconFile)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (iconFile == null)
				throw new ArgumentNullException("iconFile");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_Update",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID),
				new SqlParameter("@Name", name),
				new SqlParameter("@Index", index),
				new SqlParameter("@IconImage", getImageBytes(iconFile)),
				new SqlParameter("@IconContentType", iconFile.ContentType),
				new SqlParameter("@IconLength", iconFile.ContentLength)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryUpdateResult.Success;
				default:
					return BoardCategoryUpdateResult.InvalidCategory;
			}
		}

		public static BoardCategoryDeleteResult Remove(String componentID, String categoryID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_Delete",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryDeleteResult.Success;
				default:
					return BoardCategoryDeleteResult.InvalidCategory;
			}
		}

		public static BoardCategoryDeleteIconResult RemoveIcon(String componentID, String categoryID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_DeleteIcon",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryDeleteIconResult.Success;
				case 1:
					return BoardCategoryDeleteIconResult.InvalidCategory;
				default:
					return BoardCategoryDeleteIconResult.EmptyIcon;
			}
		}

		public static BoardCategoryMoveResult Move(String componentID, String sourceCategoryID, String destComponentID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (sourceCategoryID == null)
				throw new ArgumentNullException("sourceCategoryID");

			if (destComponentID == null)
				throw new ArgumentNullException("destComponentID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(sourceCategoryID))
				throw new ArgumentOutOfRangeException("sourceCategoryID");

			if (String.IsNullOrEmpty(destComponentID))
				throw new ArgumentOutOfRangeException("destComponentID");

			if (!VUtility.IsGuid(sourceCategoryID))
				throw new FormatException("sourceCategoryID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_Move",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", sourceCategoryID),
				new SqlParameter("@NewComponentID", destComponentID)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return BoardCategoryMoveResult.Success;
				case 1:
					return BoardCategoryMoveResult.InvalidSourceCategory;
				case 2:
					return BoardCategoryMoveResult.InvalidDestBoard;
				default:
					return BoardCategoryMoveResult.ExistsDestCategory;
			}
		}

		private static Byte[] getImageBytes(HttpPostedFile iconFile)
		{
			Int32 length = iconFile.ContentLength;

			Byte[] binaryImage = new Byte[length];

			iconFile.InputStream.Read(binaryImage, 0, length);

			return binaryImage;
		}

		internal static BoardCategory Fill(SqlDataReader reader)
		{
			BoardCategory category = new BoardCategory();
			category.ApplicationName = reader["ApplicationName"].ToString();
			category.ComponentID = reader["ComponentID"].ToString();
			category.CategoryID = reader["CategoryID"].ToString();
			category.Name = reader["Name"].ToString();
			category.Index = Convert.ToInt32(reader["Index"]);
			category.ThreadCount = Convert.ToInt32(reader["ThreadCount"]);
			category.HasIconImage = reader["IconContentType"] == System.DBNull.Value ? false : true;
			category.IconImageUrl = BoardUtil.GetBoardCategoryIconUrl(category.ComponentID, category.CategoryID);
			return category;
		}

		internal static BoardCategory Fill(DataRow row)
		{
			BoardCategory category = new BoardCategory();
			category.ApplicationName = row["ApplicationName"].ToString();
			category.ComponentID = row["ComponentID"].ToString();
			category.CategoryID = row["CategoryID"].ToString();
			category.Name = row["Name"].ToString();
			category.Index = Convert.ToInt32(row["Index"]);
			category.ThreadCount = Convert.ToInt32(row["ThreadCount"]);
			category.HasIconImage = row["IconContentType"] == System.DBNull.Value ? false : true;
			category.IconImageUrl = BoardUtil.GetBoardCategoryIconUrl(category.ComponentID, category.CategoryID);
			return category;
		}


		public static BoardCategory GetCategoryByName(String componentID, String name)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_GetBoardCategoryByName",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@Name", name)
			);

			BoardCategory category = null;

			try
			{
				if (reader.HasRows)
				{
					reader.Read();
					category = Fill(reader);
				}
			}
			finally
			{
				reader.Close();
			}

			return category;
		}

		public static BoardCategory GetCategoryByID(String componentID, String categoryID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_GetBoardCategoryByID",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID)
			);

			BoardCategory category = null;

			try
			{
				if (reader.HasRows)
				{
					reader.Read();
					category = Fill(reader);
				}
			}
			finally
			{
				reader.Close();
			}

			return category;
		}

		public static BoardCategoryCollection GetCategoryCollection(String componentID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_GetBoardCategories",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID)
			);

			BoardCategoryCollection boardCategoryCollection = null;

			try
			{
				if (reader.HasRows)
				{
					boardCategoryCollection = new BoardCategoryCollection();

					while (reader.Read())
					{
						boardCategoryCollection.Add(Fill(reader));
					}
				}
			}
			finally
			{
				reader.Close();
			}

			return boardCategoryCollection;
		}

		public static BoardCategory GetTotalityCategory(String componentID, String name, String imageUrl)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			BoardCategory totality = new BoardCategory();
			totality.ApplicationName = VWebConfigurationReader.ApplicationName;
			totality.ComponentID = componentID;
			totality.CategoryID = "";
			totality.Index = 0;
			totality.Name = name;
			totality.ThreadCount = Board.GetBoard(componentID).GetThreadCollectionCount("", "");
			totality.IconImageUrl = imageUrl;

			if (!String.IsNullOrEmpty(imageUrl))
				totality.HasIconImage = true;

			return totality;
		}

		public static Byte[] GetIcon(String componentID, String categoryID, out String fileType)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (categoryID == null)
				throw new ArgumentNullException("categoryID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(categoryID))
				throw new ArgumentOutOfRangeException("categoryID");

			if (!VUtility.IsGuid(categoryID))
				throw new FormatException("categoryID must Guid.");

			Byte[] image = null;
			fileType = "";

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure, "VWeb_BoardCategory_GetBoardCategoryIcon",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@CategoryID", categoryID)
			);

			try
			{
				if (reader.HasRows)
				{
					reader.Read();

					image = Convert.IsDBNull(reader["IconImage"]) ? null : (Byte[])reader["IconImage"];
					fileType = reader["IconContentType"].ToString();
				}
			}
			finally
			{
				reader.Close();
			}

			return image;
		}
	}

	public class BoardCategoryCollection : Collection<BoardCategory> { }
}
